﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kooboo.IoC;
using Kooboo.Commerce.Contexts.Products;
using Kooboo.Commerce.Contexts.Taxes;
using Kooboo.Domain;



namespace Kooboo.Commerce.Contexts.Orders
{
    public static class IEditorBehavior
    {
        public static void Post(this IEditor actor, IOrder order)
        {
            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    actor.UpdateTotal(order);

                    order.OrderDate = DateTime.Now;
                    var repository = ContextContainer.Current.Resolve<IOrderRepository>();
                    repository.Post(order);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        public static void Put(this IEditor actor, IOrder order)
        {

            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    var repository = ContextContainer.Current.Resolve<IOrderRepository>();
                    repository.Put(order);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        public static void Delete(this IEditor actor, IOrder order)
        {

            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    order.OrderItems
                        .ToDelete()
                        .Execute();

                    var repository = ContextContainer.Current.Resolve<IOrderRepository>();
                    repository.Delete(order);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        public static void UpdateTotal(this IEditor actor, IOrder order)
        {
            order.Total = 0;

            order.TotalTaxCost = 0;
            order.ShippingCost = 0;
            order.PaymentMethodCost = 0;
            order.Discount = 0;
            order.SubTotal = 0;
            order.TotalDiscount = 0;

            var products = actor.QueryProducts();

            //total
            foreach (var i in order.OrderItems.ToArray())
            {
                var product = products
                    .Where(n => n.Id == i.ProductId)
                    .FirstOrDefault();

                if (product == null)
                {
                    order.OrderItems.Remove(i);
                    break;
                }

                
                var saleitem = product
                    .SaleItems
                    .Where(n => n.Id == i.SaleItemId)
                    .FirstOrDefault();

                if (saleitem == null)//TODO: check stock
                {
                    order.OrderItems.Remove(i);
                    break;
                }


                i.OrderItemVariations = new List<IOrderItemVariation>();
                foreach (var n in saleitem.ProductVariations)
                {
                    var item = ObjectContainer.CreateInstance<IOrderItemVariation>();
                    item.Id = -1;
                    item.Name = n.Variation.Name;
                    item.Value = n.Value;

                    i.OrderItemVariations.Add(item);
                }

                i.UnitPrice = saleitem.RetailPrice;
                i.SKU = saleitem.SKU;
                
                
                i.SubTotal = i.UnitPrice * i.Quantity;
                i.Discount = 0;
            }

            //TODO: update shipping cost
            //shipping cost
           

            var context = new PromotionContext();

            //context.Status = CheckoutStatus.Total;
            //discount for product
            ExecutePromotions(order,context);


            var taxes = actor.QueryTaxes();
       
            //tax cost
            foreach (var i in order.OrderItems)
            {
                var product = products
                   .Where(n => n.Id == i.ProductId)
                   .FirstOrDefault();

                var saleitem = product
                    .SaleItems
                    .Where(n => n.Id == i.SaleItemId)
                    .FirstOrDefault();

                //TODO: taxes

                //var tax = taxes.FindTax(product,saleitem, order.InvoiceCountry, order.InvoiceState);
                //if (tax == null)
                //{
                //    i.TaxCost = 0;
                //}
                //else
                //{
                //    i.TaxCost = i.SubTotal* tax.Percent / 100;
                //}

                i.Total = i.SubTotal + i.TaxCost - i.Discount;
            }

            ReTotal(order);

            //context.Status = CheckoutStatus.Tax;
            //discount for tax
            ExecutePromotions(order, context);

            
            //payment cost


            var host = new ServiceHost();

            //var method = host.LocatePayment(order);

            //if (method != null && method.IsEnable)
            //{
            //    if (method.AmountChange.HasValue)
            //    {
            //        order.PaymentMethodCost = method.AmountChange.Value;
            //    }
            //    else
            //    {
            //        if (method.PercentChange.HasValue)
            //        {
            //            order.PaymentMethodCost = (order.Total + order.ShippingCost) * method.PercentChange.Value / 100;
            //        }
            //        else
            //        {
            //            order.PaymentMethodCost = decimal.Zero;
            //        }
            //    }

            //}

           // context.Status = CheckoutStatus.Pay;
            //discount for payment cost
            ExecutePromotions(order,context);


            ReTotal(order);
        }

        private static List<string> ExecutePromotions(IOrder cart, PromotionContext context)
        {
            var user = ContextContainer.Current.Resolve<Kooboo.Connect.User>();
            var errors = new List<string>();

            var rules = ContextContainer.Current.Resolve<IPromotionRuleRepository>().PromotionRules;
            foreach (var i in rules.Where(i => i.IsEnable).OrderByDescending(i => i.Priority))
            {
                var promotion = i.FindPromotion();
                if (promotion != null)
                {
                    promotion.Execute(i, user, context);
                }
            }

            return errors;
        }

        private static void ReTotal(IOrder order)
        {
            order.Total = 0;
            order.TotalTaxCost = 0;
            order.SubTotal = 0;
            order.TotalDiscount = 0;

            foreach (var i in order.OrderItems)
            {
                //product sub total
                i.SubTotal = i.UnitPrice * i.Quantity;

                //total = subtotal - discount + tax
                i.Total = i.SubTotal - i.Discount + i.TaxCost;

                //tax
                order.TotalTaxCost += i.TaxCost;
                //discount
                order.TotalDiscount += i.Discount;
                //product sub total
                order.SubTotal += i.SubTotal;
            }

            order.TotalDiscount += order.Discount;

            order.Total = order.SubTotal + order.TotalTaxCost - order.TotalDiscount;
        }
    }
}
